home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1995 Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * As a special exception, the Free Software Foundation gives permission
- * for additional uses of the text contained in its release of GUILE.
- *
- * The exception is that, if you link the GUILE library with other files
- * to produce an executable, this does not by itself cause the
- * resulting executable to be covered by the GNU General Public License.
- * Your use of that executable is in no way restricted on account of
- * linking the GUILE library code into it.
- *
- * This exception does not however invalidate any other reasons why
- * the executable file might be covered by the GNU General Public License.
- *
- * This exception applies only to the code released by the
- * Free Software Foundation under the name GUILE. If you copy
- * code from other Free Software Foundation releases into a copy of
- * GUILE, as the General Public License permits, the exception does
- * not apply to the code that you add in this way. To avoid misleading
- * anyone as to the status of such modified files, you must delete
- * this exception notice from them.
- *
- * If you write modifications of your own for GUILE, it is your choice
- * whether to permit this exception to apply to your modifications.
- * If you do not wish that, delete this exception notice.
- */
-
-
- #include <stdio.h>
- #include "_scm.h"
-
-
-
-
- /* {Catch and Throw}
- */
- static int tc16_jmpbuffer;
-
- #define JMPBUFP(O) (TYP16(O) == tc16_jmpbuffer)
- #define JBACTIVE(O) (CAR (O) & (1L << 16L))
- #define ACTIVATEJB(O) (CAR (O) |= (1L << 16L))
- #define DEACTIVATEJB(O) (CAR (O) &= ~(1L << 16L))
- #define JBJMPBUF(O) ((jmp_buf*)CDR (O) )
-
-
- #ifdef __STDC__
- static int
- printjb (SCM exp, SCM port, int writing)
- #else
- static int
- printjb (exp, port, writing)
- SCM exp;
- SCM port;
- int writing;
- #endif
- {
- scm_puts ("#<jmpbuffer ", port);
- scm_puts (JBACTIVE(exp) ? "(active) " : "(inactive) ", port);
- scm_intprint(CDR(exp), 16, port);
- scm_putc ('>', port);
- return 1 ;
- }
-
- static scm_smobfuns jbsmob = {scm_mark0, scm_free0, printjb, 0};
-
- #ifdef __STDC__
- static SCM
- make_jmpbuf (void)
- #else
- static SCM
- make_jmpbuf ()
- #endif
- {
- SCM answer;
- NEWCELL (answer);
- DEFER_INTS;
- {
- CAR(answer) = tc16_jmpbuffer;
- JBJMPBUF(answer) = (jmp_buf *)0;
- DEACTIVATEJB(answer);
- }
- ALLOW_INTS;
- return answer;
- }
-
-
-
- PROC (s_catch, "catch", 3, 0, 0, scm_catch);
- #ifdef __STDC__
- SCM
- scm_catch (SCM tag, SCM thunk, SCM handler)
- #else
- SCM
- scm_catch (tag, thunk, handler)
- SCM tag;
- SCM thunk;
- SCM handler;
- #endif
- {
- jmp_buf buf;
- SCM jmpbuf;
- SCM answer;
-
- ASSERT ((tag == BOOL_F) || (NIMP(tag) && SYMBOLP(tag)) || (tag == BOOL_T),
- tag, ARG1, s_catch);
- jmpbuf = make_jmpbuf ();
- answer = EOL;
- dynwinds = scm_acons (tag, jmpbuf, dynwinds);
- JBJMPBUF(jmpbuf) = &buf;
- if (setjmp (buf))
- {
- SCM throw_args;
- DEFER_INTS;
- DEACTIVATEJB (jmpbuf);
- dynwinds = CDR (dynwinds);
- ALLOW_INTS;
- throw_args = scm_throwval;
- scm_throwval = EOL;
- answer = scm_apply (handler, scm_cons (tag, throw_args), EOL);
- }
- else
- {
- ACTIVATEJB (jmpbuf);
- answer = scm_apply (thunk,
- ((tag == BOOL_F) ? scm_cons (jmpbuf, EOL) : EOL),
- EOL);
- DEFER_INTS;
- DEACTIVATEJB (jmpbuf);
- dynwinds = CDR (dynwinds);
- ALLOW_INTS;
- }
- return answer;
- }
-
-
- static char s_throw[];
- SCM scm_bad_throw_vcell;
- #ifdef __STDC__
- SCM
- _scm_throw (SCM key, SCM args, int noreturn)
- #else
- SCM
- _scm_throw (key, args, noreturn)
- SCM key;
- SCM args;
- int noreturn;
- #endif
- {
- SCM jmpbuf;
- if (NIMP (key) && JMPBUFP (key))
- {
- jmpbuf = key;
- if (noreturn)
- {
- ASSERT (JBACTIVE (jmpbuf), jmpbuf,
- "throw to dynamicly inactive catch",
- s_throw);
- }
- else if (!JBACTIVE (jmpbuf))
- return UNSPECIFIED;
- }
- else
- {
- SCM dynpair;
- if (noreturn)
- {
- ASSERT (NIMP (key) && SYMBOLP (key), key, ARG1, s_throw);
- }
- else if (!(NIMP (key) && SYMBOLP (key)))
- return UNSPECIFIED;
-
- dynpair = scm_assoc (key, dynwinds);
-
- if (dynpair == BOOL_F)
- dynpair = scm_assoc (BOOL_T, dynwinds);
-
- if ((dynpair == BOOL_F)
- && (BOOL_T == scm_procedurep (CDR (scm_bad_throw_vcell))))
- {
- SCM answer;
- answer = scm_apply (CDR (scm_bad_throw_vcell), scm_cons (key, args), EOL);
- }
-
- if (noreturn)
- {
- ASSERT (dynpair != BOOL_F,
- scm_cons (key, args),
- "missing CATCH", s_throw);
- }
- else if (dynpair == BOOL_F)
- return UNSPECIFIED;
-
- jmpbuf = CDR (dynpair);
- }
- scm_throwval = args;
- longjmp (*JBJMPBUF (jmpbuf), 1);
- }
-
-
-
- PROC (s_throw, "throw", 1, 0, 1, scm_throw_exception);
- #ifdef __STDC__
- SCM
- scm_throw_exception (SCM key, SCM args)
- #else
- SCM
- scm_throw_exception (key, args)
- SCM key;
- SCM args;
- #endif
- {
- _scm_throw (key, args, 1);
- return BOOL_F; /* never really returns */
- }
-
-
-
-
- PROC (s_dynamic_root, "dynamic-root", 0, 0, 0, scm_dynamic_root);
- #ifdef __STDC__
- SCM
- scm_dynamic_root (void)
- #else
- SCM
- scm_dynamic_root ()
- #endif
- {
- return scm_ulong2num (SEQ (rootcont));
- }
-
-
-
- #ifdef __STDC__
- void
- scm_init_throw (void)
- #else
- void
- scm_init_throw ()
- #endif
- {
- tc16_jmpbuffer = scm_newsmob (&jbsmob);
- #include "throw.x"
- }
-
-